package com.code.ape.codeape.common.security.component;

import cn.hutool.core.util.StrUtil;
import com.alibaba.ttl.TransmittableThreadLocal;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.env.Environment;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextHolderStrategy;
import org.springframework.security.core.context.SecurityContextImpl;

/**
 * @author 公众号：码猿技术专栏
 * 自定义Spring Security 上下文策略容器，使用阿里开源的TTL，这样保证了异步线程之间的用户信息的传递
 */
@RequiredArgsConstructor
public class TTLSecurityContextHolderStrategy implements SecurityContextHolderStrategy, ApplicationRunner {

	private final Environment environment;

    private final ThreadLocal<SecurityContext> contextHolder = new TransmittableThreadLocal<>();

    @Override
    public void clearContext() {
        contextHolder.remove();
    }

    @Override
    public SecurityContext getContext() {
        return contextHolder.get();
    }

    @Override
    public void setContext(SecurityContext context) {
        contextHolder.set(context);
    }

    @Override
    public SecurityContext createEmptyContext() {
        return new SecurityContextImpl();
    }

	@Override
	public void run(ApplicationArguments args) throws Exception {
    	//此处兼容Spring Security 内部的逻辑，通过VM参数选择内置的策略，如果项目未指定，则默认使用自定义的TTLSecurityContextHolderStrategy
//		String property = environment.getProperty(SecurityContextHolder.SYSTEM_PROPERTY);
//		if (StrUtil.isBlank(property)){
//			SecurityContextHolder.setContextHolderStrategy(this);
//		}
	}
}
